package clock.socoolby.com.clock.widget.animatorview;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.WindowManager;

import java.util.ArrayList;
import java.util.Random;

public abstract class AbstractAnimator<T extends I_AnimatorEntry> implements I_Animator{
    protected Random rand=new Random();
    protected boolean isRuning=false;
    protected int color=200;
    protected View mainView;
    protected Context context;

    protected boolean randColor=false;

    //效果场景宽高
    protected int width;
    protected int height;

    protected ArrayList<T> list = new ArrayList<>();
    protected ValueAnimator animator;

    protected int entryQuantity=DYNAMIC_QUANTITY;

    public static final int DYNAMIC_QUANTITY=0;

    protected Paint mPaint=new Paint();

    public AbstractAnimator(int entryQuantity) {
        this.entryQuantity = entryQuantity;
    }

    @Override
    public void init(Context context, final View main) {
        mainView=main;
        this.context=context;
        width=main.getWidth();
        height=main.getHeight();
    }

    @Override
    public void start() {
        if(animator==null) {
            init();
            //初始化animator
            animator = ValueAnimator.ofFloat(0, 1);
            animator.setRepeatCount(ValueAnimator.INFINITE);
            animator.setDuration(500);

            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator arg0) {
                    if(run())
                      mainView.invalidate();
                }
            });
        }
        if(!animator.isRunning())
            animator.start();
        isRuning=true;
    }

    protected void init(){
        initPaint(mPaint);
        initEntryList();
    }

    protected void initEntryList(){
        for(int i=0;i<entryQuantity;i++)
            list.add(createNewEntry());
    }

    private int dialy=0;
    public  boolean run(){
        if(dialy-->0)
            return false;
        dialy=dialyTime();
        for(T entry:list)
            entry.move(width,height);
        return true;
    }

    public int dialyTime(){
        return 0;
    }

    @Override
    public void onDraw(Canvas canvas) {
        for(T entry:list)
            entry.onDraw(canvas,mPaint);
    }

    public abstract T createNewEntry();

    public void setRandColor(boolean randColor){
        this.randColor=randColor;
    }

    protected void randomColorIfAble(){
        if(randColor){
            int alpha = 200;
            int r = rand.nextInt(255);
            int g = rand.nextInt(255);
            int b = rand.nextInt(255);
            color = alpha << 24 | r << 16 | g << 8 | b;
        }
    }

    protected void initPaint(Paint mPaint){
        mPaint.reset();
    }

    protected void beforeRemoveAnimatorEntry(T entry){

    }


    public  void reset(){
        if(entryQuantity!=DYNAMIC_QUANTITY) {
            for (T entry : list)
                beforeRemoveAnimatorEntry(entry);
            list.clear();
        }
        randomColorIfAble();
        init();
    }

    @Override
    public void restart() {
        pause();
        reset();
        start();
    }

    @Override
    public void pause() {
        if(animator==null)
            return;
            //throw new Exception("place start it first..");
        if(animator.isRunning())
            animator.cancel();
        isRuning=false;
    }

    @Override
    public void stop() {
        if(animator==null)
            return;
        if(animator.isRunning())
            animator.cancel();
        animator.removeAllUpdateListeners();
        list.clear();
        animator = null;
        isRuning=false;
    }

    @Override
    public boolean isRunning() {
        return isRuning;
    }

    @Override
    public void setColor(int color) {
        this.color=color;
    }

    @Override
    public void onSizeChanged(int w, int h, int oldw, int oldh) {
         width=w;
         height=h;
         if(isRuning)
            restart();
    }

    @Override
    public boolean isColorUseAble() {
        return true;
    }

    @Override
    public boolean isRandColor() {
        return randColor;
    }


    public static class Util {

        public static int roundColor(){
               Random rand=new Random();
               int alpha = 200;
               int r = rand.nextInt(255);
               int g = rand.nextInt(255);
               int b = rand.nextInt(255);
               return alpha << 24 | r << 16 | g << 8 | b;
        }
        /**
         * px = dp * (dpi / 160)
         *
         * @param ctx
         * @param dip
         * @return
         */
        public static int dipToPX(final Context ctx, float dip) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dip, ctx.getResources().getDisplayMetrics());
        }


        public static int getScreenWidth(Context context) {
            WindowManager wm = (WindowManager) context
                    .getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            return wm.getDefaultDisplay().getWidth();
        }

        public static int getScreenHeight(Context context) {
            WindowManager wm = (WindowManager) context
                    .getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics dm = new DisplayMetrics();
            wm.getDefaultDisplay().getMetrics(dm);
            return dm.heightPixels;
        }

        public static Bitmap drawableToBitmap(Drawable drawable) {

            int w = drawable.getIntrinsicWidth();
            int h = drawable.getIntrinsicHeight();


            Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
                    : Bitmap.Config.RGB_565;

            Bitmap bitmap = Bitmap.createBitmap(w, h, config);

            Canvas canvas = new Canvas(bitmap);
            drawable.setBounds(0, 0, w, h);

            drawable.draw(canvas);
            return bitmap;
        }

        /**
         * 重绘Drawable，将drawable颜色着色为color
         * @param drawable
         * @param color
         * @return 重绘后的Drawable
         */
        public static Drawable tint(Drawable drawable, int color)
        {
            final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
            wrappedDrawable.mutate();
            DrawableCompat.setTint(wrappedDrawable, color);
            return wrappedDrawable;
        }

        /**
         * 对rgb色彩加入透明度
         * @param alpha     透明度，取值范围 0.0f -- 1.0f.
         * @param baseColor
         * @return a color with alpha made from base color
         */
        public static int getColorWithAlpha(int baseColor,float alpha) {
            int a = Math.min(255, Math.max(0, (int) (alpha * 255))) << 24;
            int rgb = 0x00ffffff & baseColor;
            return a + rgb;
        }

    }
}
